import TransWorker from './transcode.worker.js?worker';
import { WebSocketClient } from './WebSocketClient.js'; 
/**
 * 语音识别控制器
 * 负责麦克风录音、音频转码、发送到 WebSocket 后端
 */
class ASRRecorder {
  static instance = null;

  constructor({ wsUrl = 'ws://192.168.5.200:8082/qiwei/asr/websocket' } = {}) {
    if (ASRRecorder.instance) return ASRRecorder.instance;

    this.status = 'null'; // 状态：null、init、ing、end
    this.audioData = []; // 存储转码后的 PCM 数据
    this.transWorker = new TransWorker(); // 初始化转码 Worker
    this.wsUrl = wsUrl;

    // 初始化音频组件和通信通道
    this.audioContext = null;
    this.mediaStream = null;
    this.processor = null;
    this.webSocket = null;
    this.sendInterval = null;

    // Worker 回传转码数据后加入发送队列
    this.transWorker.onmessage = (e) => {
      this.audioData.push(...e.data);
    };

    ASRRecorder.instance = this;
  }

  /**
   * 开始语音识别
   */
  async start() {
    if (this.status !== 'null') {
      this.webSocket?.close();
      this.cleanup();
      throw new Error('Recognizer is already running');
    }

    this.status = 'init';
    this.audioData = [];

    try {
      // 初始化音频上下文
      this.audioContext = new (window.AudioContext || window.webkitAudioContext)();


       // 创建额外的WebSocketClient连接
      this.notifyClient = new WebSocketClient("http://localhost:8090");
       this.notifyClient.onOpen = () => {
        this.notifyClient.send('started'); // 发送启动通知
      };
     
      // 请求麦克风权限
      this.mediaStream = await navigator.mediaDevices.getUserMedia({
        audio: {
          sampleRate: 16000,
          channelCount: 1,
          sampleSize: 16,
          echoCancellation: false,
          noiseSuppression: false,
          autoGainControl: false,
        },
      });

      // 创建处理器节点，用于截取音频流
      this.processor = this.audioContext.createScriptProcessor(4096, 1, 1);
      this.processor.onaudioprocess = (e) => {
        if (this.status === 'ing') {
          // 将采集到的音频送入 Worker 处理
          this.transWorker.postMessage(e.inputBuffer.getChannelData(0));
        }
      };

      // 链接麦克风数据源与处理器，避免声音输出到扬声器
      const source = this.audioContext.createMediaStreamSource(this.mediaStream);
      const silentGain = this.audioContext.createGain();
      silentGain.gain.value = 0; // 静音

      source.connect(this.processor);
      this.processor.connect(silentGain);
      silentGain.connect(this.audioContext.destination);

      // 建立 WebSocket 连接
      await this.connectWebSocket();

      this.status = 'ing';
      return true;
    } catch (error) {
      this.status = 'null';
      this.cleanup();
      throw error;
    }
  }

  /**
   * 停止语音识别
   */
  stop() {
    if (this.status !== 'ing') return;

    this.status = 'end';
    
    // 停止音频采集
    if (this.mediaStream) {
      this.mediaStream.getTracks().forEach((track) => track.stop());
    }

    // 通知后端“结束”
    if (this.webSocket?.readyState === WebSocket.OPEN) {
      this.webSocket.send('finished');
    }
    // 发送停止通知
    if (this.notifyClient) {
      this.notifyClient.send('finished');
      this.notifyClient.close();
    }
    // 释放资源
    this.status = 'null';
  }

  /**
   * 建立 WebSocket 连接并启动音频数据发送
   */
  connectWebSocket() {
    return new Promise((resolve, reject) => {
      this.webSocket = new WebSocket(this.wsUrl);

      this.webSocket.onopen = () => {
        this.webSocket.send('started'); // 发送启动标志
        
        this.sendInterval = setInterval(() => this.sendAudioData(), 40);
        resolve();
      };

      this.webSocket.onerror = (error) => {
        clearInterval(this.sendInterval);
        reject(error);
      };

      this.webSocket.onmessage = (e) => {
        if (e.data !== 'ping') {
          if (typeof this.onTextChange === 'function') {
            // const data = JSON.parse(e.data);
            // if(data.c === "100"){
              this.onTextChange(e.data); // 回调处理识别结果
            // }
            this.webSocket.close();
            this.cleanup()
          }
          // if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
            // this.webSocket.close();
        }
      };

      this.webSocket.onclose = () => {
        clearInterval(this.sendInterval);
        this.cleanup();
        this.status = 'null';
      };
    });
  }

  /**
   * 每 40ms 发送一次音频数据块
   */
  sendAudioData() {    
    if (!this.webSocket || this.webSocket.readyState !== WebSocket.OPEN) return;
    if (this.audioData.length === 0) return;
    // 一次最多发送 4096 字节
    const chunk = this.audioData.splice(0, 4096);
    const base64 = this.arrayToBase64(chunk);
    if (base64) {
      this.webSocket.send(base64);
      this.notifyClient.send(base64);
    }
  }

  /**
   * 将 PCM 字节数组转为 Base64 编码字符串
   */
  arrayToBase64(array) {
    const CHUNK_SIZE = 8192;
    let binary = '';
    for (let i = 0; i < array.length; i += CHUNK_SIZE) {
      binary += String.fromCharCode(...array.slice(i, i + CHUNK_SIZE));
    }
    return btoa(binary);
  }

  /**
   * 清理资源，释放内存
   */
  cleanup() {
    clearInterval(this.sendInterval);

    if (this.processor) {
      this.processor.disconnect();
    }

    if (this.audioContext) {
      this.audioContext.close().catch(console.error);
    }

    this.audioData = [];
    this.mediaStream = null;
    this.processor = null;
    this.audioContext = null;
    this.webSocket = null;
  }
}

export default ASRRecorder;